package com.zhxin.nettylab.reactor.chapter1;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * @ClassName ReactorDemo
 * @Description //单线程Reactor反应器模式 Demo
 * @Author singleZhang
 * @Email 405780096@qq.com
 * @Date 2020/12/4 0004 下午 3:34
 **/
public class ReactorDemo implements Runnable{

    private static Selector selector;
    private static ServerSocketChannel serverSocketChannel;

    ReactorDemo() throws IOException {
        selector = Selector.open();

        serverSocketChannel = ServerSocketChannel.open(); //打开ServerSocketChannel,获取通道
        serverSocketChannel.configureBlocking(false); //设为非阻塞

        ServerSocket serverSocket = serverSocketChannel.socket();
        serverSocket.bind(new InetSocketAddress(8989)); //将该通道对应的serverSocket绑定到port端口
        SelectionKey sk = serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//将通道注册到选择器上,监听"接收连接"事件

        sk.attach(new AcceptHandler());
    }

    public void run(){
        try {
            // 选择器轮询
            while (! Thread.interrupted()){
                selector.select();
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
                while(keyIterator.hasNext()){
                    SelectionKey key = keyIterator.next();
                    dispatch(key);
                }
                selectionKeys.clear();
            }
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 反应器的分发
     * */
    private void dispatch(SelectionKey key){
        Runnable rKey = (Runnable) key.attachment();
        if(rKey != null){
            rKey.run();
        }
    }

    /**
     * 新连接 处理器
     * */
    class AcceptHandler implements Runnable{

        public void run(){
            System.out.println("开始 新连接 处理");
            try{
                //接受新连接
                SocketChannel socket = serverSocketChannel.accept();
                if(socket != null){
                    // 为新连接创建一个输入输出的Handler处理器
                    new IOHandler(selector,socket);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

}
